   import java.io.*;
   import java.net.*;
   import java.util.*;
   import java.sql.SQLException;

    public final class WebServer 
   {
       public static void main(String argv[]) throws Exception
      {
      //set the port number.
         int port = 7878;
      
      //establish the listen socket.
         ServerSocket listenSocket = new ServerSocket(port);
      
      //process HTTP service requests in an infinite loop
         while(true)
         {
         //listen for a TCP connection request.
         //construct an object to process the HTTP request message.
            HttpRequest request = new HttpRequest(listenSocket.accept());
         
         //create a new thread to process the request.
            Thread thread = new Thread(request);
         
         //start the thread
            thread.start();			
         }		
      }
   }

    final class HttpRequest implements Runnable
   {
      final static String CRLF = "\r\n";
   
      Socket socket;
   
   //constructor
       public HttpRequest(Socket socket) throws Exception
      {
         this.socket = socket;
      }
   
   //implement the run() method of the Runnable interface
       public void run()
      {
         try
         {
            processRequest();
         }
             catch(Exception e)
            {
               e.printStackTrace();
            }		
      }
   
       private void processRequest() throws Exception
      {
      //get a reference to the socket's input and output streams.
         InputStream is = this.socket.getInputStream() ;
         DataOutputStream os =  new DataOutputStream(this.socket.getOutputStream());
      
      //set up input stream filters
      
         BufferedReader br =  new BufferedReader(new InputStreamReader(is));
      
      //get the request line line of the HTTP request message
         String requestLine = br.readLine() ;
      
       //display the request line
         System.out.println();
         System.out.println(requestLine);
      
        //now we'll parse the get line and get an array of the variables passed in the get.
		String[][] arguments = parseGet(requestLine);
		String parsedArguments[] = parseArguments(arguments);
		
		String fileName = invokeResponse(parsedArguments);

        System.out.println("THE TEST WORKED IF THIS SAYS test:  " + fileName);
      
        // Open the requested file.  
         FileInputStream fis = null;
         boolean fileExists = true;
         try {
            fis = new FileInputStream(fileName);
         } 
             catch (FileNotFoundException e) {
			   System.out.println("The File does not exist");
               fileExists = false;
            }
      
        // Construct the response message.
         String statusLine = null;
         String contentTypeLine = null;
         String entityBody = null;
            
         if (fileExists) {
			System.out.println("The file exists!!!!");
            statusLine = "HTTP/1.0 200 OK" + CRLF;
            contentTypeLine = "Content-type: " + contentType(fileName) + CRLF;
         } 
         else {
            statusLine = "HTTP/1.0 404 Not Found" + CRLF; 
            contentTypeLine = "NONE";
            entityBody = "\n\n Not Found";
         }
        
        // Send the status line.
         os.writeBytes(statusLine);
        
        // Send the content type line.
         os.writeBytes(contentTypeLine);
        
        // Send a blank line to indicate the end of the header lines.
         os.writeBytes(CRLF);
        
        // Send the entity body.
         if (fileExists) {
			System.out.println("The file exists!!!!");
            sendBytes(fis, os);
            fis.close();
         } 
         else {
            os.writeBytes(entityBody);
         }		
      
      //close streams and socket
         os.close();
         br.close();
         socket.close();
      }	
   	
		private String[] parseArguments(String[][] argumentsIn)
		{
			String[] argumentsOut;
			//there will be room for more validation in the next iteration.
			if(argumentsIn.length == 4)
			{
				/*
				 * Test:
				 * ArgumentIn 0 = runCode ("test")		ArgumentOut 0 = runCode("test")
				 * ArgumentIn 1 = sourceFile			ArgumentOut 1 = sourceFile
				 * ArgumentIn 2 = expectedOutput		ArgumentOut 2 = expectedOutput
				 * ArgumentIn 3 = generatedOutputName	ArgumentOut 3 = generatedOutputName
				 */
				
				argumentsOut = new String[4];
			}
			
			if(argumentsIn.length == 3)
			{
			
				/*
				 * Generate:
				 * ArgumentIn 0 = date					ArgumentOut 0 = runCode ("generate")
				 * ArgumentIn 1 = runCode ("generate")	ArgumentOut 1 = date
				 * ArgumentIn 2 = authorID				ArgumentOut 2 = authorId
				 * 
				 */
				
				argumentsOut = new String[3];
				argumentsOut[0] = argumentsIn[1][1];
				argumentsOut[1] = argumentsIn[0][1];
				argumentsOut[2] = argumentsIn[2][1];
				
			
			}
			else if(argumentsIn.length == 2)
			{

				argumentsOut = new String[2];
				argumentsOut[0] = argumentsIn[1][1];
				argumentsOut[1] = argumentsIn[0][1];
			
			}
			else
			{
				argumentsOut = new String[2];
				argumentsOut[0] = "error";
				argumentsOut[1] = "error";
			}
			
			return argumentsOut;
		}
	
		private String invokeResponse(String[] argumentsIn) throws SQLException, IOException
		{
		
			String filenameOut;
			SGResponse response = new SGResponse(argumentsIn);
			filenameOut = response.getFilename();
			return filenameOut;
		
		}
	
       private String[][] parseGet(String get)
      {
		 String[][] array;
         int find_question_mark = get.indexOf("?");
      
         String get_substring = get.substring(find_question_mark+1);
      
      
         int find_space = get_substring.indexOf(" ");
         String get1 = get_substring.substring(0, find_space); 
      	
      
         int count_and = countIndexOf(get1, "&");
      	
         if(count_and == 2)
         {                  
            array = new String[count_and+1][2];
         
            for(int i = 0; i < count_and+1; i++)
            {
               if(i != count_and)
               {
                  int find_equal = get1.indexOf("=");
                  int find_and1 = get1.indexOf("&");
               
                  array[i][0] = get1.substring(0, find_equal);
                  if(i == 0)
                  {
                     String date = get1.substring(find_equal+1, find_and1);
                     date = date.replaceAll("%2F","/");
                     array[i][1] = date;
                  }
                  else
                  {
                     array[i][1] = get1.substring(find_equal+1, find_and1);
                  }        
                  System.out.println(array[i][0]);  
                  System.out.println(array[i][1]); 
               
                  get1 = get1.substring(find_and1+1);                       
               }
               else
               {
                  int find_equal = get1.indexOf("=");				
               
                  array[i][0] = get1.substring(0, find_equal);
                  array[i][1] = get1.substring(find_equal+1);
               
                  System.out.println(array[i][0]);  
                  System.out.println(array[i][1]);               
               }
            }
         }
         else if(count_and == 1)
         {
            array = new String[count_and+1][2];
         
            for(int i = 0; i < count_and+1; i++)
            {
               if(i != count_and)
               {
                  int find_equal = get1.indexOf("=");
                  int find_and1 = get1.indexOf("&");
               
                  array[i][0] = get1.substring(0, find_equal);
                  array[i][1] = get1.substring(find_equal+1, find_and1);
                          
                  System.out.println(array[i][0]);  
                  System.out.println(array[i][1]); 
               
                  get1 = get1.substring(find_and1+1);                       
               }
               else
               {
                  int find_equal = get1.indexOf("=");				
               
                  array[i][0] = get1.substring(0, find_equal);
                  array[i][1] = get1.substring(find_equal+1);
               
                  System.out.println(array[i][0]);  
                  System.out.println(array[i][1]);               
               }
            }         	
         }    
		else
			array = new String[2][2];
		//return the array of variables parsed from the get line.
		return array;
		 
      }
   	
       private int countIndexOf(String text, String search)
      {
         int count = 0;
         for (int fromIndex = 0; fromIndex > -1; count++)
            fromIndex = text.indexOf(search, fromIndex + ((count > 0) ? 1 : 0));
         return count - 1;
      }
   
   	
   
       private String contentType(String fileName) {
         if(fileName.endsWith(".htm") || fileName.endsWith(".html"))
            return "text/html";
         else if(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))
            return "image/jpeg";
         else if(fileName.endsWith(".gif"))
            return "image/gif";
         else if(fileName.endsWith(".txt"))
            return "text/plain";
         else
            return "application/octet-stream";
      }
         
       private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception {
        // Construct a 1K buffer to hold bytes on their way to the socket.
         byte[] buffer = new byte[1024];
         int bytes = 0;
        
        // Copy requested file into the socket's output stream.
         while((bytes = fis.read(buffer)) != -1 )
            os.write(buffer, 0, bytes);
      }
   
   }
